package org.flintparticles.twoD.stage3d.images
{

	import flash.display3D.Context3D;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.VertexBuffer3D;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.Point;
	
	import org.flintparticles.common.stage3d.Vao;
	import org.flintparticles.common.stage3d.utils.Stage3DMath;
	
	public class GeomEntity2D extends EventDispatcher
	{
	   private var _x:Number
	   private var _y:Number;
	   private var _pivot:Point=new Point();
	   private var _scaleX:Number;
	   private var _scaleY:Number;
	   private var _rotation:Number;
	   private var _alpha:Number=1;
	   private var _visible:Boolean;
	   private var _transform:Matrix3D;
	   
	   protected var _vao:Vao;
	   protected static var _vertexBuffer:VertexBuffer3D;
	   protected static var _indexBuffer:IndexBuffer3D;
	   protected var _context:Context3D;
		public function GeomEntity2D()///!!!!!!!!!!don't init directly!!!!
		{
			
		//	throw new Error("Abstract class ,no direct init!");
			//_stageMath=new Stage3DMath();///////used by every geom object to get transformation data
			_x = _y = _rotation = 0.0;
		//	_pivot.setTo(0,0);
			_scaleX = _scaleY = _alpha = 1.0;            
			
		}
		protected function createVertexBuffer():void{
			
			if(!_vertexBuffer){
			
			  _vertexBuffer = _context.createVertexBuffer(4, Vao.ELEMENTS_PER_VERTEX);
			  _vertexBuffer.uploadFromVector(vertexData.data, 0, 4);
			
			}
			
			
		}
		protected function createIndexBuffer():void
		{
			if (!_indexBuffer) {
				_indexBuffer = _context.createIndexBuffer(6);
				_indexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 1, 3, 2]), 0, 6);
				
			}
		}
		protected function updateVertexBuffer():void{
			_vertexBuffer.uploadFromVector(vertexData.data, 0, 4);
		}
		public function get context():Context3D
		{
			return _context;
		}
		
		public function set context(value:Context3D):void
		{
			_context = value;
			if (_vertexBuffer == null) createVertexBuffer();
			if (_indexBuffer  == null) createIndexBuffer();
			_context.setVertexBufferAt(0, _vertexBuffer, Vao.POSITION_OFFSET, Context3DVertexBufferFormat.FLOAT_3);
			_context.setVertexBufferAt(1, _vertexBuffer, Vao.COLOR_OFFSET,    Context3DVertexBufferFormat.FLOAT_4);
			
		}
		public function set vertexData(value:Vao):void
		{ 
			_vao=value;
		}
		public function get vertexData():Vao
		{ 
			return _vao.clone(); 
		}
		
		public function draw(stageMath:Stage3DMath):void{
			throw new Error("Abstract class ,no direct init!");
		}
      
		/** Disposes all resources of the display object. 
		 * GPU buffers are released, event listeners are removed. */
		public function dispose():void
		{
			//removeEventListeners();
		}
		
		
		
		////////////////////////getters/setters//////////////////////////////
		/** The transformation matrix of the object relative to its parent. */
		public function get transformationMatrix():Matrix
		{
			var matrix:Matrix = new Matrix();
			
			if (_pivot.x != 0.0 || _pivot.y != 0.0) matrix.translate(-_pivot.x, -pivot.y);
			if (_scaleX != 1.0 || _scaleY != 1.0) matrix.scale(_scaleX, _scaleY);
			if (_rotation != 0.0)                 matrix.rotate(_rotation);
			if (_x != 0.0 || _y != 0.0)           matrix.translate(_x, _y);
			
			return matrix;
		}
	   public function get transform():Matrix3D
	   {
		   return _transform;
	   }

	   public function set transform(value:Matrix3D):void
	   {
		   _transform = value;
	   }

	   public function get x():Number
	   {
		   return _x;
	   }

	   public function set x(value:Number):void
	   {
		   _x = value;
	   }

	   public function get y():Number
	   {
		   return _y;
	   }

	   public function set y(value:Number):void
	   {
		   _y = value;
	   }

	   public function get rotation():Number
	   {
		   return _rotation;
	   }

	   public function set rotation(value:Number):void
	   {
		   while (value < -Math.PI) value += Math.PI * 2.0;
		   while (value >  Math.PI) value -= Math.PI * 2.0;
		  _rotation = value;
	   }

	   public function get alpha():Number
	   {
		   return _alpha;
	   }

	   public function set alpha(value:Number):void
	   {
		   if(value==alpha)return;
		   _alpha = Math.max(0.0, Math.min(1.0, value)); 
	   }

	   public function get scaleX():Number
	   {
		   return _scaleX;
	   }

	   public function set scaleX(value:Number):void
	   {
		   _scaleX = value;
	   }

	   public function get scaleY():Number
	   {
		   return _scaleY;
	   }

	   public function set scaleY(value:Number):void
	   {
		   _scaleY = value;
	   }

	   public function get pivot():Point
	   {
		   return _pivot;
	   }

	   public function set pivot(value:Point):void
	   {
		   _pivot = value;
	   }

		
	}
}